#include "ptwrap.hpp"
#include <deque>

// [[ex04ab]]
// DEBUG descr The basic synchronized queue implemented with a semaphore.
template <class Value>
class Queue
{
public:
	Queue()
	{ 
		pthread_mutex_init(&mutex_, NULL);
		pthread_cond_init(&cond_, NULL);
	}

	virtual ~Queue()
	{ 
		pthread_mutex_destroy(&mutex_);
		pthread_cond_destroy(&cond_);
	}

	// this combines the STL front() and pop_front()
	// since the popping must be atomic
	Value pop_front()
	{
		pthread_mutex_lock(&mutex_);

		while(deque_.empty())
			pthread_cond_wait(&cond_, &mutex_);
		Value v = deque_.front();
		deque_.pop_front();

		pthread_mutex_unlock(&mutex_);
		return v;
	}

	void push_back(Value &v)
	{
		pthread_mutex_lock(&mutex_);

		bool wasempty = deque_.empty();
		deque_.push_back(v);
		if (wasempty) 
			// we know that the queue has just become
			// non-empty
			pthread_cond_broadcast(&cond_);

		pthread_mutex_unlock(&mutex_);
	}

protected:
	std::deque<Value> deque_;
	pthread_mutex_t mutex_; 
	pthread_cond_t cond_; 
};
// END

// DEBUG {
int main()
{
	Queue<int> q;
	int v1 = 1;
	q.push_back(v1);
	int v2 = q.pop_front();
	return !(v1 == v2);
}
// DEBUG }
